/*
 * Copyright (C) Microsoft Corporation. All Rights Reserved. This code released
 * under the terms of the Microsoft Public License (MS-PL,
 * http://opensource.org/licenses/ms-pl.html.)
 */

package com.microsoft.almrangers.tfsproctemplatecust.customcontrols;

import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;

import com.microsoft.tfs.client.common.ui.framework.helper.UIHelpers;
import com.microsoft.tfs.client.common.ui.wit.form.controls.LabelableControl;
import com.microsoft.tfs.core.clients.workitem.fields.Field;
import com.microsoft.tfs.core.clients.workitem.fields.FieldChangeEvent;
import com.microsoft.tfs.core.clients.workitem.fields.FieldChangeListener;
import com.microsoft.tfs.core.clients.workitem.fields.FieldType;

/**
 * Custom control which displays optional values in the form of radio buttons
 * and stores the selected value in a work item field
 * 
 */
public class CheckBoxControl
    extends LabelableControl
{
    private Button checkBoxButton;

    @Override
    protected int getControlColumns()
    {
        return 1;
    }

    @Override
    protected void createControl(Composite parent, int numColumns)
    {        
        final Composite composite = new Composite(parent, SWT.NONE);
        composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, numColumns, 1));
        composite.setLayout(new GridLayout(1, true));
        
        checkBoxButton = new Button(composite, SWT.CHECK);        
        checkBoxButton.setEnabled(false);
        
        // Is the control associated with a field?
        if (getControlDescription().getFieldName() == null)
        {   
            MessageDialog.openError(parent.getShell(), "Error",String.format("No field has been associated with checkbox control %s \nControl will be disabled.", getControlDescription().getAttribute("Name")));
            return;
        }
        
        final Field workItemField = getWorkItem().getFields().getField(getControlDescription().getFieldName());
        
        if(workItemField.getFieldDefinition().getFieldType() != FieldType.BOOLEAN)
        {
            MessageDialog.openError(parent.getShell(), "Error",String.format("Invalid field type for checkbox control %s. Only Boolean field field type are supported and %s is of type %s \nControl will be disabled.", getControlDescription().getAttribute("Name"),getControlDescription().getFieldName(),workItemField.getFieldDefinition().getFieldType().getDisplayName()));
            return;
        }        
    
        // Everything validated. Enable the control and set the event handlers
        
        checkBoxButton.setEnabled(true);
        checkBoxButton.addSelectionListener(new SelectionAdapter()
        {
            public void widgetSelected(SelectionEvent e)
            {
                /*
                 * Update the work item field's value when a radio button is
                 * selected
                 */
                workItemField.setValue(checkBoxButton.getSelection());
            }
        });    

        composite.setEnabled(!isFormReadonly() && workItemField.isEditable());

        final FieldChangeListener fieldChangeListener = new FieldChangeListener()
        {
            public void fieldChanged(final FieldChangeEvent event)
            {
                UIHelpers.runOnUIThread(composite.getDisplay(), true, new Runnable()
                {
                    public void run()
                    {
                        handleFieldChanged(event);
                    }
                });
            }
        };
        workItemField.addFieldChangeListener(fieldChangeListener);

        parent.addDisposeListener(new DisposeListener()
        {
            public void widgetDisposed(DisposeEvent e)
            {
                workItemField.removeFieldChangeListener(fieldChangeListener);
            }
        });

        /*
         * fire a "fake" field change event to set the appropriate checkbox button
         */
        FieldChangeEvent fieldChangeEvent = new FieldChangeEvent();
        fieldChangeEvent.field = workItemField;
        fieldChangeListener.fieldChanged(fieldChangeEvent);
    }

    /**
     * Set the state of the checkbox based on the value of the field
     * associated with the control
     * 
     * @param event
     */
    private void handleFieldChanged(FieldChangeEvent event)
    {
        Field field = event.field;
                
        boolean newValue = field.getValue() == null ? false : (Boolean)field.getValue();        
        
        checkBoxButton.setSelection(newValue);
    }
}
